package com.qinggeng.project.api.controller;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.*;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.utils.DateUtils;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.framework.config.thread.ThreadPoolExecutorUtil;
import com.qinggeng.framework.redis.RedisCache;
import com.qinggeng.framework.redis.RedisLock;
import com.qinggeng.framework.web.controller.BaseController;
import com.qinggeng.framework.web.domain.AjaxResult;
import com.qinggeng.project.api.dto.*;
import com.qinggeng.project.api.security.annotation.LoginRequired;
import com.qinggeng.project.api.security.utils.ApiUtils;
import com.qinggeng.project.api.utils.EmojiUtils;
import com.qinggeng.project.api.utils.OrdersCheckUtils;
import com.qinggeng.project.api.utils.PhoneNumberUtils;
import com.qinggeng.project.system.domain.*;
import com.qinggeng.project.system.domain.vo.DistributionPointVO;
import com.qinggeng.project.system.domain.vo.OrdersSingleGoodsReturnVO;
import com.qinggeng.project.system.domain.vo.ReturnOrdersGoodsVO;
import com.qinggeng.project.system.dto.OrdersSingleGoodsReturnDTO;
import com.qinggeng.project.system.service.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Api(tags = "订单模块")
@RestController
@RequestMapping("${apiPath}/orders")
@CrossOrigin
@Slf4j
public class ApiOrdersController extends BaseController {

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IGoodsClassifyService goodsClassifyService;

    @Autowired
    private IUserAddressService userAddressService;

    @Autowired
    private IShopService shopService;

    @Autowired
    private IDistributionPointService distributionPointService;

    @Autowired
    private IUserCartService userCartService;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private DistributionConfigService distributionConfigService;

    @Autowired
    private IOrdersService ordersService;

    @Autowired
    private IOrdersPointService ordersPointService;

    @Autowired
    private IOrdersGoodsService ordersGoodsService;

    @Autowired
    private IOrdersReturnService ordersReturnService;

    @Autowired
    private IOrdersCourierService ordersCourierService;

    @Autowired
    private IUserLocationService userLocationService;

    @Autowired
    private ICostFreeService costFreeService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private OrdersDistService ordersDistService;

    @Autowired
    private UserBeatService userBeatService;

    @Autowired
    private IOrdersGiftService ordersGiftService;

    @Autowired
    private IAssistRecordService recordService;

    @Autowired
    private IGoodsGiftService goodsGiftService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private MQSendService mqSendService;
    @Resource
    private RedissonClient redissonClient;
    @Autowired
    private IOrdersEvaluateService ordersEvaluateService;
    @Autowired
    private OrdersCheckUtils ordersCheckUtils;


    @Autowired
    private UserAccountRecordOrderSingleItemService userAccountRecordOrderSingleItemService;

    @Autowired
    private IUserGoodsLimitRecordService userGoodsLimitRecordService;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private ShareOrdersService shareOrdersService;
    @Autowired
    private ISysActivityService sysActivityService;
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private MemberService memberService;

    @ApiOperation("单商品预下单详情")
    @GetMapping("/goodsOrdersInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "goodsId", value = "商品ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "goodsNum", value = "商品数量", dataType = "Integer", paramType = "query", required = false),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "ordersType", value = "商品类型 10=普通商品 20=免费送 30=拼团商品 40=商家补贴 50=捶一捶", defaultValue = "10", dataType = "String", paramType = "query"),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @CrossOrigin
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult goodsOrdersInfo(Long goodsId, @RequestParam(defaultValue = "1") Integer goodsNum, Long shopId, String pickPhone, Long addressId, Long pointId, String distType, String distTime, String pickTime, Float lng, Float lat, String remark, @RequestParam(defaultValue = "10") String ordersType) {
        try {
            GoodsInfoDto goodsInfoDto = goodsService.selectGoodsDtoById(goodsId, shopId, lng, lat);
            if (goodsInfoDto == null) {
                return AjaxResult.error("商品不存在");
            }
            //商品限购
            userGoodsLimitRecordService.checkIsGoodsLimit(goodsId,goodsNum,0);
            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(ordersType, distTime, pickTime, pickPhone, remark);
            //单商品下单
            ordersInfoDto.setOrdersCharacter("1");
            //初始化地址与配送时间
            distAddressPriceInit(distType, addressId, pointId, shopId, ordersInfoDto, lng, lat, false);
            //商品列表( 订单类型为 20=免费送时，商品数量设置为1)
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            goodsDtoList.add(new AddOrdersInfoGoodsDto(goodsInfoDto, ordersType.equals("20") ? 1 : goodsNum));
            ordersInfoDto.setGoodsList(goodsDtoList);
            //商品总价=商品价格*商品数量（免费订单商品数量 为1）
            BigDecimal totalPrice = goodsInfoDto.getGoodsPrice().multiply(new BigDecimal(ordersType.equals("20") ? 1 : goodsNum));
            //优惠价格(免费订单优惠价格为订单总额，否则优惠价格为0)
            BigDecimal reducePrice = ordersType.equals(OrdersTypeEnum.免费送.getValue()) ? totalPrice : new BigDecimal(0);
            //设置订单展示价格
            ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, distType);
            if (ordersType.equals(OrdersTypeEnum.免费送.getValue()) && goodsNum > 1) {
                return AjaxResult.success("免费商品只能领取一个", ShowTypeEnum.用户.getValue(), ordersInfoDto);
            }

            return AjaxResult.success(ordersInfoDto);
        } catch (CustomException e) {
            if (e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("单商品下单")
    @PostMapping("/goodsOrdersAdd")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "goodsNum", value = "商品数量", dataType = "Integer", paramType = "query", required = false),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "ordersType", value = "商品类型 10=普通商品 20=免费送 30=拼团商品 40=商家补贴 50=捶一捶", defaultValue = "10", dataType = "String", paramType = "query"),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @CrossOrigin
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult goodsOrdersAdd(Long goodsId, @RequestParam(defaultValue = "1") Integer goodsNum, Long shopId, String pickPhone, Long addressId, Long pointId, String distType, String distTime, String pickTime, String remark, @RequestParam(defaultValue = "10") String ordersType, Float lng, Float lat) {
        try {
            GoodsInfoDto goodsInfoDto = goodsService.selectGoodsDtoById(goodsId, shopId);
            if (goodsInfoDto == null) {
                return AjaxResult.error("商品不存在");
            }
            if (goodsInfoDto.getKeepNum() <= 0) {
                return AjaxResult.error("已被抢光", ShowTypeEnum.用户.getValue());
            }

            //捶一捶活动商品
            if (ordersType.equals(OrdersTypeEnum.捶一捶.getValue())) {
                //判断当天是否超过捶一捶次数
                JSONObject configObject = JSONObject.parseObject(sysConfigService.selectConfigByKey("sys.beat.peopleCount").toString());
                int count = userBeatService.selectCountTodayByUserId(ApiUtils.getUserId());
                if (count >= Integer.parseInt(configObject.getString("peopleCount"))) {
                    return AjaxResult.error("今日已用完" + count + "机会,请明天再来哦", ShowTypeEnum.用户.getValue());
                }
                goodsInfoDto.setGoodsPrice(new BigDecimal(0).setScale(2, BigDecimal.ROUND_HALF_DOWN));
            }

            if (ordersType.equals(OrdersTypeEnum.免费送.getValue())) {
                CostFree costFree = costFreeService.selectCostFreeByUserId(ApiUtils.getUserId());
                //免费领取次数
                int freeCount = Integer.parseInt(sysConfigService.selectConfigByKey("sys.orders.freeCount").toString());
                if (costFree != null && costFree.getCount() >= freeCount) {
                    return AjaxResult.error("每日限领" + freeCount + "次，今日已领完，请明日再来！", ShowTypeEnum.用户.getValue());
                }
                goodsInfoDto.setGoodsPrice(new BigDecimal(0).setScale(2, BigDecimal.ROUND_HALF_DOWN));
            }
            if (goodsInfoDto.getKeepNum() < goodsNum) {
                return AjaxResult.error("已被抢光", ShowTypeEnum.用户.getValue());
            }
            //商品限购
            //商品限购
            userGoodsLimitRecordService.checkIsGoodsLimit(goodsId,goodsNum,0);
            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(ordersType, distTime, pickTime, pickPhone, remark);
            //配送方式
            ordersInfoDto.setDistType(distType);
            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            goodsDtoList.add(new AddOrdersInfoGoodsDto(goodsInfoDto, goodsNum));
            ordersInfoDto.setGoodsList(goodsDtoList);
            //初始化地址与配送时间
            distAddressPriceInit(distType, addressId, pointId, shopId, ordersInfoDto, lng, lat, true);
            //商品总价格=商品单价*商品数量
            BigDecimal totalPrice = goodsInfoDto.getGoodsPrice().multiply(new BigDecimal(goodsNum));
            //商品vip总价格=商品单价*商品数量
            BigDecimal vipPrice = goodsInfoDto.getVipPrice().multiply(new BigDecimal(goodsNum));

            //优惠价格
            BigDecimal reducePrice = ordersType.equals(OrdersTypeEnum.免费送.getValue()) ? totalPrice : new BigDecimal(0);
            //判断用户是不是会员
            Long userId=ApiUtils.getUserId();
            Integer  memberCode= memberService.isVip(userId);
            //设置订单展示价格
            if (MemberEnum.MEMBER.equals(memberCode)){
                //设置订单展示价格
                ordersService.setPrice(ordersInfoDto, vipPrice, reducePrice, distType);
            }else {
                ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, distType);
            }
            //创建订单
            Orders orders = ordersService.createOrders(distType, ordersInfoDto, ApiUtils.getUserId());

            if(ordersType.equals(OrdersTypeEnum.普通订单.getValue())){
                sysActivityService.insertOrdersGift(orders.getOrdersId());
            }

            //如果商品类型为20=免费送商品
            if (ordersType.equals(OrdersTypeEnum.免费送.getValue())) {
                //更新订单支付状态为20=已支付 并发送mq消息
                ordersService.updateOrdersPayStatusAndSendMessages(orders.getOrdersId());
                //更新免费领取的记录
                costFreeService.updateCostFreeRecord(ApiUtils.getUserId());
            }

            if (ordersType.equals(OrdersTypeEnum.捶一捶.getValue())) {
                //设置订单支付状态为20=已支付
                ordersService.updateFreePayOrdersPayStatus(orders.getOrdersId());
            }
            Map<String, Object> data = Maps.newHashMap();
            data.put("ordersNo", orders.getOrdersNo());
            data.put("totalPrice", orders.getTotalPrice());
            data.put("payPrice", orders.getPayPrice());
            data.put("distPrice", orders.getDistPrice());
            data.put("payOutTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", orders.getPayOutTime()));
            data.put("ordersId", orders.getOrdersId());
            return AjaxResult.success(data);
        } catch (CustomException e) {
            if (e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("购买单商品")
    @PostMapping("/vipGoodsOrders")
    @CrossOrigin
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult vipGoodsOrders(Long goodsId) {
        try {
            GoodsInfoDto goodsInfoDto = goodsService.selectGoodsDtoById(goodsId, 6L);
            if (goodsInfoDto == null) {
                return AjaxResult.error("商品不存在");
            }
            String vipType="20";
            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(vipType, "", "", "", "");
            Shop shop=new Shop();
            shop.setId(6L);
            ordersInfoDto.setShop(shop);
            //配送方式
            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            goodsDtoList.add(new AddOrdersInfoGoodsDto(goodsInfoDto, 1));
            ordersInfoDto.setGoodsList(goodsDtoList);
            DistributionPointDto dto=new DistributionPointDto();
            dto.setId(0L);
            ordersInfoDto.setPoint(dto);
            //商品总价格=商品单价*商品数量
            BigDecimal totalPrice = goodsInfoDto.getGoodsPrice().multiply(new BigDecimal(1));
            //设置订单展示价格
            ordersService.setPrice(ordersInfoDto, totalPrice);
            ordersInfoDto.setReducePrice(BigDecimal.ZERO);
            ordersInfoDto.setDistPrice(BigDecimal.ZERO);
            //创建订单
            Orders orders = ordersService.createOrders(vipType, ordersInfoDto, ApiUtils.getUserId());
            Map<String, Object> data = Maps.newHashMap();
            data.put("ordersNo", orders.getOrdersNo());
            data.put("totalPrice", orders.getTotalPrice());
            data.put("payPrice", orders.getPayPrice());
            data.put("distPrice", orders.getDistPrice());
            data.put("payOutTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", orders.getPayOutTime()));
            data.put("ordersId", orders.getOrdersId());
            return AjaxResult.success(data);
        } catch (CustomException e) {
            e.printStackTrace();
            if (e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("预买肉送菜接口")
    @GetMapping("/beforeCartOrdersInfo")
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult beforeCartOrdersInfo(String cartIds,String totalPrice) {
        try {
            Map<String, String> data = userCartService.judgeCartHaveBuyGoodsPlus(cartIds,totalPrice);
            return AjaxResult.success(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error("错误",ShowTypeEnum.后台.getValue());
    }


    @ApiOperation("购物车预下单详情")
    @GetMapping("/cartOrdersInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cartIds", value = "购物车Id 逗号分隔", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "bsJudge", value = "是否参与卖肉送菜 1参与 0不参与"),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult cartOrdersInfo(String cartIds, Long shopId, Long addressId, Long pointId, String pickPhone, String distType, String distTime, String pickTime, Float lng, Float lat, String remark, String bsJudge,@RequestParam(defaultValue = "0") String shareStatus) {
        try {
            if (StringUtils.isEmpty(cartIds)) {
                return AjaxResult.error("购物车ID数组为空");
            }
            String[] cartIdsArray = cartIds.split(",");
            List<CartDto> cartDtoList = Lists.newArrayList();

            List<CartDto> cartDtos = userCartService.selectUserCartDtoByIds(cartIdsArray);
            if (cartDtos == null || cartDtos.size()==0) {
                return AjaxResult.error("购物车不存在");
            }
            userGoodsLimitRecordService.checkIsGoodsLimitList(cartDtos);

            cartDtoList.addAll(cartDtos);
            if (cartDtoList.size() <= 0) {
                return AjaxResult.error("请选择商品", ShowTypeEnum.用户.getValue());
            }
            //优惠信息
            List<FavorableDTO> favorableDTOS = null;
            //参与买肉送菜
            BigDecimal addMoney = new BigDecimal("0");
            if (bsJudge.equals("1")) {
                String config = (String) sysConfigService.selectConfigByKey("sys.buy.send");
                JSONObject params = JSONObject.parseObject(config);
                if (StringUtils.isEmpty(params)) {
                    throw new CustomException("ApiOrdersController.cartOrdersInfo()[params is null]");
                }
                if (params.getString("open").equals("1")) {
                    String buyClassifyName = params.getString("buyClassifyName");
                    String sendClassifyName = params.getString("sendClassifyName");
                    //要送的个数
                    String amount = params.getString("amount");
                    String money = params.getString("money");
                    addMoney = addMoney.add(new BigDecimal(money));
                    //获取父分类名称等于此条件的子分类集合
                    //要买的种类
                    List<Long> buyClassifyIds = goodsClassifyService.selectGoodsClassifyIdsByCondition(buyClassifyName);
                    //要送的种类
                    List<Long> sendClassifyIds = goodsClassifyService.selectGoodsClassifyIdsByCondition(sendClassifyName);

                    //过滤出购物车中不含买的品种的对象
                    List<CartDto> collectNotBuy = cartDtoList.stream().filter(a -> {
                        return buyClassifyIds.stream().filter(b -> {
                            return b.equals(a.getClassifyId());
                        }).count() <= 0;
                    }).collect(Collectors.toList());
                    //集合元素个数不相等说明含有需要买的对象
                    if (collectNotBuy.size() > 0 && collectNotBuy.size() != cartDtoList.size()) {
                        //过滤出含有送出的对象
                        List<CartDto> collectHaveSend = collectNotBuy.stream().filter(a -> {
                            return sendClassifyIds.stream().filter(b -> {
                                return b.equals(a.getClassifyId());
                            }).count() >= 1;
                        }).collect(Collectors.toList());

                        if (collectHaveSend.size() > 0) {
                            //就集合中对象商品数量的和
                            int sum = collectHaveSend.stream().mapToInt(CartDto::getGoodsNum).sum();
                            int count = Integer.parseInt(amount);
                            if (sum >= 1 && sum <= Integer.parseInt(amount)) {
                                Collections.shuffle(collectHaveSend);
                                favorableDTOS = new ArrayList<>();
                                a:
                                for (CartDto cartDto : collectHaveSend) {
                                    for (int i = 0; i < cartDto.getGoodsNum(); i++) {
                                        if (count == 0) {
                                            break a;
                                        }
                                        FavorableDTO favorableDTO = new FavorableDTO();
                                        favorableDTO.setGoodsName(cartDto.getGoodsName());
                                        favorableDTO.setPrice(cartDto.getGroupPrice());
                                        favorableDTO.setGoodsId(cartDto.getGoodsId());
                                        favorableDTOS.add(favorableDTO);
                                        count--;
                                    }
                                }
                            }

                            if (sum > Integer.parseInt(amount)) {
                                Collections.shuffle(collectHaveSend);
                                favorableDTOS = new ArrayList<>();
                                a:
                                for (CartDto cartDto : collectHaveSend) {
                                    for (int i = 0; i < cartDto.getGoodsNum(); i++) {
                                        if (count == 0) {
                                            break a;
                                        }
                                        FavorableDTO favorableDTO = new FavorableDTO();
                                        favorableDTO.setGoodsName(cartDto.getGoodsName());
                                        favorableDTO.setPrice(cartDto.getGroupPrice());
                                        favorableDTO.setGoodsId(cartDto.getGoodsId());
                                        favorableDTOS.add(favorableDTO);
                                        count--;
                                    }
                                }
                            }
                        }

                    }

                }
            }

            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(OrdersTypeEnum.普通订单.getValue(), distTime, pickTime, pickPhone, remark);
            //拼团下单
            ordersInfoDto.setOrdersCharacter("2");

            //设置换购价

            BigDecimal totalPrice = new BigDecimal(0);

            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            //判断用户是不是会员
            Long userId=ApiUtils.getUserId();
            Integer  memberCode= memberService.isVip(userId);
            log.info("购物车支付验证会员 userId{}  memberCode{} ",userId,memberCode);
            boolean bl=MemberEnum.MEMBER.getKey().equals(memberCode);
            for (CartDto cartDto : cartDtoList) {
                goodsDtoList.add(new AddOrdersInfoGoodsDto(cartDto));
                //商品总价=商品总价+商品团购价格*商品数量
                //设置订单展示价格
                if (bl){
                    totalPrice = totalPrice.add(cartDto.getVipPrice().multiply(new BigDecimal(cartDto.getGoodsNum())));
                }else {
                    totalPrice = totalPrice.add(cartDto.getGroupPrice().multiply(new BigDecimal(cartDto.getGoodsNum())));
                }
            };
            log.info("是否是会员 {}",bl);

            if (addMoney != null) {
                ordersInfoDto.setExchangePrice(addMoney);
            }

            //设置空值给前台
            if (favorableDTOS == null) {
                favorableDTOS = new ArrayList<>();
            }

            ordersInfoDto.setFavorableDTOS(favorableDTOS);
            //设置优惠价格
            BigDecimal reducePrice = new BigDecimal("0");
            for (FavorableDTO favorableDTO : favorableDTOS) {
                reducePrice = reducePrice.add(favorableDTO.getPrice());
            }

            ordersInfoDto.setGoodsList(goodsDtoList);
            //初始化地址与配送时间
            distAddressPriceInit(distType, addressId, pointId, shopId, ordersInfoDto, lng, lat, false);
            //设置订单展示价格


            ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, distType);
            ordersInfoDto.setPayPrice(ordersInfoDto.getPayPrice().add(addMoney));
            ordersInfoDto.setGiftList(new ArrayList<>());
            //送油卡
            if (ShareStatusEnum.YES.getCode().equals(shareStatus)){
                ordersInfoDto.setShareStatus(shareStatus);
                JSONObject params = JSONObject.parseObject((String) sysConfigService.selectConfigByKey("sys.send.oil"));
                String soloMoney = params.getString("soloMoney");
                if (StringUtils.isEmpty(soloMoney)){
                    soloMoney = "10";
                }
                long num = ordersInfoDto.getTotalPrice().divide(new BigDecimal(soloMoney), 0, BigDecimal.ROUND_DOWN).longValue();
                GoodsGift goodsGift = goodsGiftService.selectGoodsGiftById(30L);
                OrdersGift ordersGift = new OrdersGift(goodsGift,num);
                List<OrdersGift> ordersGifts = new ArrayList<>();
                ordersGifts.add(ordersGift);
                ordersInfoDto.setGiftList(ordersGifts);
            }



            return AjaxResult.success(ordersInfoDto);
        } catch (CustomException e) {
            if (e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("购物车下单")
    @PostMapping("/cartOrdersAdd")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cartIds", value = "购物车Id 逗号分隔", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 MM-dd HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult cartOrdersAdd(@RequestBody CartOrdersAddParamsDTO cartOrdersAddParamsDTO) {
        RLock lock = redissonClient.getLock("CARTORDERSADD:" + ApiUtils.getUserId());
        if (lock.isLocked()){
            return AjaxResult.error("请勿重复操作",ShowTypeEnum.用户.getValue());
        }
        lock.lock();
        try {
            String cartIds = cartOrdersAddParamsDTO.getCartIds();
            if (StringUtils.isEmpty(cartIds)) {
                return AjaxResult.error("购物车ID数组为空");
            }
            String[] cartIdsArray = cartIds.split(",");
            List<CartDto> cartDtoList = Lists.newArrayList();
            //失效商品名称集合
            List<String> loseGoodsNameList = Lists.newArrayList();

            List<CartDto> cartDtos = userCartService.selectUserCartDtoByIds(cartIdsArray);
            if (cartDtos == null || cartDtos.size()==0) {
                return AjaxResult.error("购物车不存在");
            }
            userGoodsLimitRecordService.checkIsGoodsLimitList(cartDtos,loseGoodsNameList);

            cartDtoList.addAll(cartDtos);

            if (loseGoodsNameList.size() > 0) {
                return AjaxResult.error(loseGoodsNameList.toString() + "商品已下架，请重新选择！", ShowTypeEnum.用户.getValue());
            }
            if (cartDtoList.size() <= 0) {
                return AjaxResult.error("请选择商品", ShowTypeEnum.用户.getValue());
            }
            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(OrdersTypeEnum.普通订单.getValue(), cartOrdersAddParamsDTO.getDistTime(), cartOrdersAddParamsDTO.getPickTime(), cartOrdersAddParamsDTO.getPickPhone(), cartOrdersAddParamsDTO.getRemark());

            BigDecimal totalPrice = new BigDecimal(0);


            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();

            //判断用户是不是会员
            Long userId=ApiUtils.getUserId();
            Integer  memberCode= memberService.isVip(userId);
            //设置订单展示价格
            boolean bl=MemberEnum.MEMBER.getKey().equals(memberCode);

            for (CartDto cartDto : cartDtoList) {
                AddOrdersInfoGoodsDto addOrdersInfoGoodsDto = new AddOrdersInfoGoodsDto(cartDto);
                //商品总价=商品总价+商品团购价格*商品数量
                if (bl){
                    addOrdersInfoGoodsDto.setGroupPrice(cartDto.getVipPrice());
                    totalPrice=totalPrice.add(cartDto.getVipPrice().multiply(new BigDecimal(cartDto.getGoodsNum())));
                }else {
                    totalPrice = totalPrice.add(cartDto.getGroupPrice().multiply(new BigDecimal(cartDto.getGoodsNum())));
                }
                goodsDtoList.add(addOrdersInfoGoodsDto);
            }

            ordersInfoDto.setGoodsList(goodsDtoList);
            ordersInfoDto.setOrdersType(cartOrdersAddParamsDTO.getOrdersType());
            //初始化地址与配送时间
            distAddressPriceInit(cartOrdersAddParamsDTO.getDistType(), cartOrdersAddParamsDTO.getAddressId(), cartOrdersAddParamsDTO.getPointId(), cartOrdersAddParamsDTO.getShopId(), ordersInfoDto, cartOrdersAddParamsDTO.getLng(), cartOrdersAddParamsDTO.getLat(), true);
            //设置优惠价格
            BigDecimal reducePrice = new BigDecimal("0");
            if (!CollectionUtils.isEmpty(cartOrdersAddParamsDTO.getFavorableDTOS())){
                for (FavorableDTO favorableDTO : cartOrdersAddParamsDTO.getFavorableDTOS()) {
                    reducePrice = reducePrice.add(favorableDTO.getPrice());
                }
            }

            //设置订单展示价格
            ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, cartOrdersAddParamsDTO.getDistType());
            //换购价
            if (cartOrdersAddParamsDTO.getExchangePrice() != null) {
                ordersInfoDto.setPayPrice(ordersInfoDto.getPayPrice().add(cartOrdersAddParamsDTO.getExchangePrice()));
            }

            //创建订单
            Orders orders = ordersService.createOrders1(cartOrdersAddParamsDTO.getDistType(), ordersInfoDto, ApiUtils.getUserId(),cartOrdersAddParamsDTO.getFavorableDTOS());

            if(StringUtils.isNotEmpty(orders.getOrdersType())&&orders.getOrdersType().equals(OrdersTypeEnum.普通订单.getValue())){
                sysActivityService.insertOrdersGift(orders.getOrdersId());
            }

            //下单成功商品从购物车删除
            Long courierId = cartOrdersAddParamsDTO.getCourierId();
            if (courierId != null && courierId != 0){
                shareOrdersService.createShareOrders(orders.getOrdersId(),ApiUtils.getUserId(),courierId);
            }

            if (ShareStatusEnum.YES.getCode().equals(cartOrdersAddParamsDTO.getShareStatus())){
                List<OrdersGift> ordersGiftList = cartOrdersAddParamsDTO.getOrdersGiftList();
                if (!CollectionUtils.isEmpty(ordersGiftList)){
                    for (OrdersGift ordersGift : ordersGiftList) {
                        ordersGift.setOrdersId(orders.getOrdersId());
                        ordersGift.setUserId(ApiUtils.getUserId());
                        ordersGift.setPickFlag("20");
                        ordersGiftService.insertOrdersGift(ordersGift);
                    }
                }
            }
            //下单成功商品从购物车删除
            Long[] cartIdsForLong = new Long[cartIdsArray.length];
            for (int i = 0; i < cartIdsArray.length; i++) {
                cartIdsForLong[i] = Long.valueOf(cartIdsArray[i]);
            }
            userCartService.deleteUserCartByIds(cartIdsForLong);
            Map<String, Object> data = Maps.newHashMap();
            data.put("ordersNo", orders.getOrdersNo());
            data.put("totalPrice", orders.getTotalPrice());
            data.put("payPrice", orders.getPayPrice());
            data.put("distPrice", orders.getDistPrice());
            data.put("payOutTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", orders.getPayOutTime()));
            data.put("ordersId", orders.getOrdersId());
            //查询购物车的商品数量总和
            data.put("goodsNum", userCartService.selectUserCartGoodsNumByUserId(ApiUtils.getUserId()));
            data.put("createTime",DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,orders.getCreateTime()));
            return AjaxResult.success(data);
        } catch (CustomException e) {
            return AjaxResult.error(e.getMessage(),ShowTypeEnum.用户.getValue());
        }finally {
            lock.unlock();
        }
    }


    @ApiOperation("好友助力商品预下单详情")
    @GetMapping("/assistOrdersInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "recordId", value = "好友助力记录ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @CrossOrigin
    @LoginRequired(must = false, role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult assistGoodsOrdersInfo(Long recordId, Long shopId, String pickPhone, Long addressId, Long pointId, String distType, String distTime, String pickTime, Float lng, Float lat, String remark) {
        try {
            AssistRecord record = recordService.selectAssistRecordByIdAndUserId(recordId, ApiUtils.getUserId());
            if (record == null) {
                return AjaxResult.error("未查询到好友助力记录！", ShowTypeEnum.用户.getValue());
            }
            GoodsInfoDto goodsInfoDto = goodsService.selectGoodsDtoById(record.getGoodsId(), shopId, lng, lat);
            if (goodsInfoDto == null) {
                return AjaxResult.error("商品不存在", ShowTypeEnum.用户.getValue());
            }
            //订单类型，配送时间，自取时间，预留手机号，备注
            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(OrdersTypeEnum.好友助力.getValue(), distTime, pickTime, pickPhone, remark);
            //单商品下单
            ordersInfoDto.setOrdersCharacter("1");
            //抽中其他随机小礼品
            if (getIsWin(record, goodsGiftService.getOtherGiftId())) {
                ordersInfoDto.setGiftId(record.getGiftId());
            }
            //初始化地址与配送时间
            distAddressPriceInit(distType, addressId, pointId, shopId, ordersInfoDto, lng, lat, false);
            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            goodsDtoList.add(new AddOrdersInfoGoodsDto(goodsInfoDto, 1));
            ordersInfoDto.setGoodsList(goodsDtoList);
            //商品总价=商品拼团价格*商品数量
            BigDecimal totalPrice = goodsInfoDto.getGroupPrice().multiply(new BigDecimal(1));
            //优惠价格
            BigDecimal reducePrice = new BigDecimal(0);
            //抽中免单
            if (getIsWin(record,goodsGiftService.getFreeGiftId())) {
                reducePrice = totalPrice;
            }
            //抽中半价
            if (getIsWin(record, goodsGiftService.getHalfGiftId())) {
                reducePrice = totalPrice.multiply(new BigDecimal(0.5));
            }
            //设置订单展示价格
            ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, distType);
            //抽中随机小礼品，设置奖品列表
            boolean isOther = getIsWin(record, goodsGiftService.getOtherGiftId());
            ordersInfoDto.setGiftList(isOther ? ordersGiftService.addOrdersGiftList(record.getGiftId()) : Lists.newArrayList());
            return AjaxResult.success(ordersInfoDto);
        } catch (CustomException e) {
            if (e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }


    @ApiOperation("好友助力商品下单")
    @PostMapping("/assistOrdersAdd")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "recordId", value = "好友助力记录ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "addressId", value = "地址ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickPhone", value = "预留手机号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "remark", value = "备注", dataType = "Long", paramType = "query", required = false),
            @ApiImplicitParam(name = "distType", value = "配送方式 10=配送 20=自取", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "distTime", value = "配送时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "pickTime", value = "自取时间 HH:mm", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @CrossOrigin
    @LoginRequired(must = false, role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult assistOrdersAdd(Long recordId, Long shopId, String pickPhone, Long addressId, Long pointId, String distType, String distTime, String pickTime, String remark, Float lng, Float lat) {
        try {

            AssistRecord record = recordService.selectAssistRecordByIdAndUserId(recordId, ApiUtils.getUserId());
            if (record == null) {
                return AjaxResult.error("好友助力记录不存在");
            }
            GoodsInfoDto goodsInfoDto = goodsService.selectGoodsDtoById(record.getGoodsId(), shopId);
            if (goodsInfoDto == null) {
                return AjaxResult.error("商品不存在");
            }
            if (goodsInfoDto.getKeepNum() < 1) {
                return AjaxResult.error("已被抢光", ShowTypeEnum.用户.getValue());
            }
            //限购商品数量
            userGoodsLimitRecordService.checkIsGoodsLimit(record.getGoodsId(),1,0);

            AddOrdersInfoDto ordersInfoDto = new AddOrdersInfoDto(OrdersTypeEnum.好友助力.getValue(), distTime, pickTime, pickPhone, remark);
            //配送方式
            ordersInfoDto.setDistType(distType);

            //初始化地址与配送时间
            distAddressPriceInit(distType, addressId, pointId, shopId, ordersInfoDto, lng, lat, true);

            AddOrdersInfoGoodsDto addOrdersInfoGoodsDto=new AddOrdersInfoGoodsDto(goodsInfoDto, 1);
            //商品总价格=商品单价*商品数量
            BigDecimal totalPrice = goodsInfoDto.getGroupPrice().multiply(new BigDecimal(1));
            //优惠价格
            BigDecimal reducePrice = new BigDecimal(0);
            //抽中免单
            if (getIsWin(record, goodsGiftService.getFreeGiftId())) {
                reducePrice = totalPrice;
                addOrdersInfoGoodsDto.setDiscountStatus("1");
            }
            //抽中半价
            if (getIsWin(record, goodsGiftService.getHalfGiftId())) {
                reducePrice = totalPrice.multiply(new BigDecimal(0.5));
                addOrdersInfoGoodsDto.setDiscountStatus("1");
            }
            addOrdersInfoGoodsDto.setDiscountPrice(reducePrice);
            //商品列表
            List<AddOrdersInfoGoodsDto> goodsDtoList = Lists.newArrayList();
            goodsDtoList.add(addOrdersInfoGoodsDto);
            ordersInfoDto.setGoodsList(goodsDtoList);
            //设置订单展示价格
            ordersService.setPrice(ordersInfoDto, totalPrice, reducePrice, distType);
            //创建订单
            Orders orders = ordersService.createOrders(distType, ordersInfoDto, ApiUtils.getUserId());
            //抽中其他随机小奖品
            if (getIsWin(record, goodsGiftService.getOtherGiftId())) {
                GoodsGift goodsGift = goodsGiftService.selectGoodsGiftById(record.getGiftId());
                //20=已领取
                ordersGiftService.insertOrdersGift(orders.getOrdersId(), goodsGift, "20");
            }
            //下单成功之后将助力中奖记录改为false,防止用户重复下单
            record.setIsWin(false);
            recordService.updateAssistRecord(record);

            boolean isFree = false;
            if (orders.getPayPrice().compareTo(new BigDecimal(0)) == 0) {
                isFree = true;
                ////更新订单支付状态为20=已支付 并发送mq消息
                ordersService.updateOrdersPayStatusAndSendMessages(orders.getOrdersId());
            }
            Map<String, Object> data = Maps.newHashMap();
            data.put("ordersNo", orders.getOrdersNo());
            data.put("totalPrice", orders.getTotalPrice());
            data.put("reducePrice", orders.getReducePrice());
            data.put("payPrice", orders.getPayPrice());
            data.put("distPrice", orders.getDistPrice());
            data.put("payOutTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", orders.getPayOutTime()));
            data.put("ordersId", orders.getOrdersId());
            data.put("isFree", isFree);
            return AjaxResult.success(data);
        } catch (CustomException e) {
            return AjaxResult.error(e.getMessage(),ShowTypeEnum.用户.getValue());
        }
    }


    /**
     * 初始化地址与配送时间
     *
     * @param distType
     * @param addressId
     * @param pointId
     * @param shopId
     * @param ordersInfoDto
     * @param lng
     * @param lat
     * @param addIs
     * @throws Exception
     */
    private void distAddressPriceInit (String distType, Long addressId, Long pointId, Long shopId, AddOrdersInfoDto ordersInfoDto, Float lng, Float lat, Boolean addIs) {
        CountDownLatch cdlOne = new CountDownLatch(4);
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getPoll();
                //设置商铺
        Shop shop = shopService.selectShopById(shopId);
        if (shop == null) {
                    throw new CustomException("商家不存在");
                }
                ordersInfoDto.setShop(shop);
        //根据用户的收货地址获取列表中最近的配送点
        DistributionPointDto pointDto = null;

        if (distType.equals(OrdersDistTypeEnum.配送.getValue())) {
            AtomicReference<UserAddress> atoUserAddress = new AtomicReference<>();

            threadPoolExecutor.execute(()->{
                try {
                    atoUserAddress.set(userAddressService.selectUserAddressById(addressId));
                    //用户收货地址有效
                    if (atoUserAddress.get() != null) {
                        //设置用户收货地址;
                        ordersInfoDto.setAddress(atoUserAddress.get());
                        //设置预留手机号
                        if (StringUtils.isEmpty(ordersInfoDto.getPickPhone())) {
                            ordersInfoDto.setPickPhone(atoUserAddress.get().getAddressPhone());
                        }
                    } else {
                        atoUserAddress.set(new UserAddress(lng, lat));
                    }
                } catch (Exception e) {
                    log.info(e.getMessage(),e);
                } finally {
                    cdlOne.countDown();
                }
            });
            AtomicReference<DistributionPointDto> atoPointDto = new AtomicReference<>();
            threadPoolExecutor.execute(()->{
                //距离用户收货地址最近的配送点
                try {
                    atoPointDto.set(distributionPointService.getDistributionPointDtoNearest(atoUserAddress.get().getAddressLng(), atoUserAddress.get().getAddressLat(), shopId));
                } catch (Exception e) {
                    log.info(e.getMessage(),e);
                } finally {
                    cdlOne.countDown();
                }
            });
            //配送时间
            threadPoolExecutor.execute(()->{
                try {
                    ordersInfoDto.setDistDateTime(distributionConfigService.getDistributionDate(null, distType));
                } catch (Exception e) {
                    log.info(e.getMessage(),e);
                } finally {
                    cdlOne.countDown();
                }
            });
            threadPoolExecutor.execute(()->{
                try {
                    ordersInfoDto.setDistTime(distributionConfigService.getDistDateTime());
                } catch (Exception e) {
                    log.info(e.getMessage(),e);
                } finally {
                    cdlOne.countDown();
                }
            });
            try {
                cdlOne.await();
            } catch (InterruptedException e) {
                log.info(e.getMessage(),e);
                throw new CustomException(e.getMessage());
            }
            if (addIs) {
                if (ordersInfoDto.getAddress() == null) {
                    throw new CustomException("请选择收货地址", ShowTypeEnum.用户.getValue());
                } else if (shop.getDistScope().compareTo(ordersInfoDto.getAddress().getDistance()) < 0) {
                    throw new CustomException(500, "地址不在配送范围内", 100);
                }
            }

        }

        //配送方式为自取
        if (distType.equals(OrdersDistTypeEnum.自取.getValue())) {
            if (pointId == null) {
                //redis中获取用户上次选择的配送点Id
                pointId = redisCache.getCacheObject(Constants.POINT_KEY + ApiUtils.getUserId());
            }

            if (pointId == null) {
                //用户历史订单中获取上一次自提订单的配送点ID
                OrdersPoint ordersPoint = ordersPointService.selectOrdersPointByUserId(ApiUtils.getUserId());
                pointId = ordersPoint != null ? ordersPoint.getPointId() : null;
            }

            if (pointId != null) {
                pointDto = distributionPointService.selectDistributionPointDtoById(pointId, lng, lat);
            }

            if (null != pointDto && pointDto.getIsOpen().equals(CommonEnum.STATUS_10.getValue())) {
                //将配送点id缓存到redis中
                redisCache.setCacheObject(Constants.POINT_KEY + ApiUtils.getUserId(), pointDto.getId());
            } else {
                //如果配送点不存在或20=未开启，则默认选择最近的配送点
                pointDto = distributionPointService.getDistributionPointDtoNearest(lng, lat, shopId);
            }

            if (pointDto != null && pointDto.getIsOpen().equals(CommonEnum.STATUS_10.getValue())) {
                //设置自取时间
                ordersInfoDto.setPickTime(distributionConfigService.getPickDateTime(shop, pointDto));
            }
        }
        if (pointDto != null && pointDto.getIsOpen().equals(CommonEnum.STATUS_10.getValue())) {

            ordersInfoDto.setPoint(pointDto);
        }
    }


    @ApiOperation("配送点列表")
    @GetMapping("/pointList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "search", value = "搜索", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
    })
    public AjaxResult pointList(Float lng, Float lat, Long shopId, String search, String cityCode) {
        try {
            DistributionPoint where = new DistributionPoint();
            where.setLng(lng);
            where.setLat(lat);
            where.setShopId(shopId);
            where.setIsOpen("10");
            where.setCityCode(cityCode);
            if (StringUtils.isNotEmpty(search)){
                String result = EmojiUtils.filter(search);
                where.setPointName(result);
            }

            startPage();
            List<DistributionPointVO> distributionPointDtoList = distributionPointService.selectDistributionPointVOList(where);

            //无配送点则返回空值集合
            if (distributionPointDtoList == null || distributionPointDtoList.size() <= 0) {
                distributionPointDtoList = Lists.newArrayList();
            }
            return AjaxResult.success(distributionPointDtoList);
        }catch (Exception e)
        {
            log.error("orders.pointList={}",e.getMessage());
            return AjaxResult.error("");
        }

    }


    @GetMapping("/refundOrdersList")
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult refundOrdersList(Integer type) {
        startPage();
        OrdersSingleGoodsReturnDTO dto=new OrdersSingleGoodsReturnDTO();
        dto.setUserId(ApiUtils.getUserId());
        dto.setType(type);
        List<OrdersSingleGoodsReturnVO> list=ordersService.selectOrdersSingleGoodsReturnList(dto);
        return  AjaxResult.success(list);
    }

    @ApiOperation("订单列表")
    @GetMapping("/ordersList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "ordersIndex", value = "索引 0=全部 1=待付款 2=待配送 3=待收货 4=待评价  5=已完成 6=支付超时 7=退单中 8=已退单 9=退单失败 10 =退款或售后订单", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult ordersList(Integer ordersIndex) {
        if (null == ordersIndex) {
            throw new CustomException("传入类型");
        }
        startPage();
        Orders ordersWhere = new Orders();
        ordersWhere.setUserId(ApiUtils.getUserId());
        ordersWhere.setOrdersIndex(ordersIndex);
        ordersWhere.setDelFlag("0");
        List<Orders> ordersList = Lists.newArrayList();
        switch (ordersIndex) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                ordersList = ordersService.selectOrdersList(ordersWhere);
                break;
            case 7:
            case 8:
            case 9:
            case 10:
                ordersList = ordersService.selectOrdersReturnList(ordersWhere);
                break;
        }

        try {
            if (ordersList != null && ordersList.size() > 0) {
                List<Long> orderIdList = Lists.newArrayList();
                List<Long> shopIdList = Lists.newArrayList();
                for (Orders orders : ordersList) {
                    orderIdList.add(orders.getOrdersId());
                    shopIdList.add(orders.getShopId());
                }
                ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getPoll();

                Future<List<OrdersGoods>> future1 = threadPoolExecutor.submit(() -> {
                    List<OrdersGoods> ordersGoodsListT = ordersGoodsService.selectOrderGoodListByOrdersIds(orderIdList);

                    return ordersGoodsListT;
                });

                Future<List<OrdersGift>> future2 = threadPoolExecutor.submit(() -> {
                    List<OrdersGift> ordersGiftListT = ordersGiftService.selectOrdersGiftListByOrdersIds(orderIdList);
                    return ordersGiftListT;
                });

                Future<List<Shop>> future3 = threadPoolExecutor.submit(() -> {
                    List<Shop> shopListT = shopService.selectShopByIds(shopIdList);
                    return shopListT;
                });

                Future<List<OrdersCourier>> future4 = threadPoolExecutor.submit(() -> {
                    List<OrdersCourier> ordersCourierListT = ordersCourierService.selectOrdersCourierByOrdersIds(orderIdList);
                    return ordersCourierListT;
                });

                List<OrdersGoods> goodsList;
                List<OrdersGoods> ordersGoodsList = future1.get();
                List<OrdersGift> giftList;
                List<OrdersGift> ordersGiftList = future2.get();
                for (Orders orders : ordersList) {
                    //封装订单商品集合
                    goodsList = Lists.newLinkedList();
                    for (OrdersGoods ordersGoods : ordersGoodsList) {
                        if (ordersGoods.getOrdersId().equals(orders.getOrdersId())) {
                            goodsList.add(ordersGoods);
                        }
                    }
                    orders.setGoodsList(goodsList);
                    //封装订单奖品集合
                    giftList = Lists.newLinkedList();
                    for (OrdersGift ordersGift : ordersGiftList) {
                        if (ordersGift.getOrdersId().equals(orders.getOrdersId())) {
                            giftList.add(ordersGift);
                        }
                    }
                    orders.setGiftList(giftList);

                }

                //封装所有的商户对象
                List<Shop> shopList = future3.get();
                for (Orders orders : ordersList) {
                    for (Shop shop : shopList) {
                        if (orders.getShopId().equals(shop.getId())) {
                            orders.setShop(shop);
                        }
                    }
                }

                //封装所有订单配送信息
                List<OrdersCourier> ordersCourierList = future4.get();
                for (Orders orders : ordersList) {
                    for (OrdersCourier ordersCourier : ordersCourierList) {
                        if (orders.getOrdersId().equals(ordersCourier.getOrdersId())) {
                            orders.setCourier(ordersCourier);
                        }
                    }
                }

            } else {
                ordersList = Lists.newLinkedList();
                for (Orders orders : ordersList) {
                    orders.setGoodsList(new ArrayList<>());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("系统异常");
        }
        return AjaxResult.success(OrdersDto.newsList(ordersList));
    }


    @ApiOperation("自取时间列表")
    @GetMapping("/dateTimeList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointId", value = "配送点ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult dateTimeList(Long pointId, Long shopId) {
        Shop shop = shopService.selectShopById(shopId);
        if (shop == null) {
            return AjaxResult.error("商户不存在");
        }
        DistributionPoint point = distributionPointService.selectDistributionPointById(pointId);
        if (point == null) {
            return AjaxResult.error("配送点不存在");
        }
        try {
            return AjaxResult.success(distributionConfigService.getDistributionDateList(shop, point));
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("订单详情")
    @GetMapping("/ordersInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired
    public AjaxResult ordersInfo(Long ordersId) {
        Orders orders = ordersService.selectOrdersById(ordersId);
        if (orders == null) {
            return AjaxResult.error("订单不存在");
        }
        return AjaxResult.success(ordersService.setOrdersInfo(orders));
    }


    @ApiOperation("配送订单详情")
    @GetMapping("/distOrdersInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单编号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired
    public AjaxResult distOrdersInfo(String ordersNo) {
        OrdersDist ordersDist = ordersDistService.selectOrdersDistByOrdersNo(ordersNo);
        if (ordersDist == null) {
            return AjaxResult.error("查询信息有误", ShowTypeEnum.用户.getValue());
        }
        List<OrdersGoods> ordersGoodsList = ordersGoodsService.selectOrderGoodListByOrdersId(ordersDist.getOrdersId());
        List<OrdersGift> giftList = ordersGiftService.selectOrdersGiftListByOrdersId(ordersDist.getOrdersId());
        BigDecimal totalPrice = BigDecimal.ZERO;
        for (OrdersGoods ordersGoods : ordersGoodsList) {
            totalPrice = totalPrice.add(ordersGoods.getGoodsPrice().multiply(new BigDecimal(ordersGoods.getGoodsNum().toString())));
        }
        ordersDist.setOrdersGoodsList(ordersGoodsList);
        ordersDist.setOrdersGiftList(giftList);
        totalPrice = totalPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
        ordersDist.setTotalPrice(totalPrice);
        return AjaxResult.success(ordersDist);

    }


    @ApiOperation("订单大厅列表")
    @GetMapping("/discOrdersList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "页大小", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "status", value = "状态 1=抢单 2=待取货 3=配送中 4=已完成", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_ALL)
    public AjaxResult discOrdersList(Integer status, Float lng, Float lat) {
        Long courierId = sysUserService.selectUserIdByPhoneNumberAndUserType(ApiUtils.getApiUser().getUser().getPhonenumber(), UserTypeEnum.COURIER.getCode());
        if (courierId == null){
            throw new CustomException("当前用户没有自提点账号,courierId="+courierId);
        }
        DistributionPoint distributionPoint = distributionPointService.selectPointByCourierId(courierId);
        if (distributionPoint == null) {
            return AjaxResult.error("自提点不存在", ShowTypeEnum.用户.getValue());
        }
        startPage();
        List<OrdersDistDto> ordersDistDtoList = ordersService.selectOrdersDiscDtoList(status, lng, lat, distributionPoint.getId());
        return AjaxResult.success(ordersDistDtoList);
    }

    @ApiOperation("订单大厅抢单")
    @PostMapping("/discOrdersTake")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "lng", value = "经度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Float", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_ALL)
    public AjaxResult discOrdersTake(Long ordersId, Float lng, Float lat) {
        RedisLock redisLock = new RedisLock(redisTemplate, "ORDERS_TAKE:" + ordersId);
        try {
            if (!redisLock.lockNoRetry()) {
                return AjaxResult.error(-101, "手速慢了订单已被抢", ShowTypeEnum.用户.getValue());
            }
            ordersService.discOrdersTake(ordersId, ApiUtils.getUserId(), lng, lat);
            return AjaxResult.success("抢单成功", ShowTypeEnum.用户.getValue());
        } catch (CustomException e) {
            return AjaxResult.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("系统异常");
        } finally {
            redisLock.unlock();
        }
    }


    @ApiOperation("订单大厅确认取货")
    @PostMapping("/discOrdersAckTake")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_ALL)
    public AjaxResult discOrdersAckTake(String ordersNo) {
        RedisLock redisLock = new RedisLock(redisTemplate, "ORDERS_UPD:" + ordersNo);
        try {
            if (!redisLock.lockNoRetry()) {
                return AjaxResult.error("服务繁忙", ShowTypeEnum.用户.getValue());
            }
            ordersService.discOrdersAckTake(ordersNo, ApiUtils.getUserId());
            return AjaxResult.success("取货成功", ShowTypeEnum.用户.getValue());
        } catch (CustomException e) {
            if (e.getType() != null && e.getType() == ShowTypeEnum.用户.getValue()) {
                return AjaxResult.error(e.getMessage(), ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            return AjaxResult.error("系统异常");
        } finally {
            redisLock.unlock();
        }
    }

    @ApiOperation("订单大厅确认送达")
    @PostMapping("/discOrdersAckSend")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单编号", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "receiver", value = "签收人姓名", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_ALL)
    public AjaxResult discOrdersAckSend(String ordersNo, String receiver) {
        //取货
        return this.discOrdersAckTake(ordersNo);
        /*RedisLock redisLock = new RedisLock(redisTemplate, "ORDERS_UPD:" + ordersNo);
        try {
            if (!redisLock.lockNoRetry()) {
                return AjaxResult.error("服务繁忙", ShowTypeEnum.用户.getValue());
            }
            ordersService.discOrdersAckSend(ordersNo, ApiUtils.getUserId(), receiver);
            return AjaxResult.success("送达成功", ShowTypeEnum.用户.getValue());
        } catch (CustomException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("系统异常");
        } finally {
            redisLock.unlock();
        }*/
    }

    @ApiOperation("确认收货")
    @PostMapping("/affirmTake")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult affirmTake(Long ordersId) {
        RLock rLock=redissonClient.getLock("ORDERS_UPD:" + ordersId);
        if (rLock.isLocked()) {
            return AjaxResult.error("服务繁忙", ShowTypeEnum.用户.getValue());
        }
        try {
            rLock.lock();
            if(ordersService.affirmTake(ordersId, ApiUtils.getUserId())){
                return AjaxResult.success("确认收货成功", ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error("确认收货失败",ShowTypeEnum.用户.getValue());
        }catch (CustomException e) {
            return AjaxResult.error(e.getMessage(),ShowTypeEnum.用户.getValue());
        }catch (Exception e){
            return AjaxResult.error("系统异常");
        }finally {
            rLock.unlock();
        }
    }

    @ApiOperation("添加评价")
    @PostMapping("/addEvaluate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "ordersGoodsId", value = "订单商品ID，注意不是goodsId", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "evaluateDesc", value = "描述", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "evaluateImgs", value = "图片 多个逗号分隔", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "goodsQuality", value = "综合评价 1-5", dataType = "Integer", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult addEvaluate(Long ordersId, Long ordersGoodsId, String evaluateDesc, String evaluateImgs, Integer goodsQuality) {

        RLock lock=redissonClient.getLock("ORDERS_UPD:" + ordersGoodsId);
        if (lock.isLocked()) {
            return AjaxResult.error("服务繁忙", ShowTypeEnum.用户.getValue());
        }
        Orders orders = ordersService.selectOrdersById(ordersId);
        if (null==orders) {
            return AjaxResult.error("订单不存在");
        }
        if (!orders.getPayStatus().equals(CommonEnum.STATUS_20.getValue())) {
           return AjaxResult.error("订单未支付", ShowTypeEnum.用户.getValue());
        }
        lock.lock();
        try {
            //单商品评价
            ordersEvaluateService.addEvaluate(ordersGoodsId, orders.getShopId(),ApiUtils.getUserId(), evaluateDesc, evaluateImgs, goodsQuality,"0");
            //检查订单所有商品是否完结
            if(ordersGoodsService.checkOrdersGoodsIsAllEnd(ordersId)){
                //更新订单状态为完结状态
                if(!ordersService.updateOrdersEndStatus(ordersId)){
                    throw new CustomException("更新完结状态失败");
                }
                //订单返现
                if(!userAccountService.orderPayMoney(orders.getOrdersNo())){
                    throw new CustomException("返现失败");
                }
            }
            return AjaxResult.success("评价成功",ShowTypeEnum.用户.getValue());
        } catch (Exception e){
            return AjaxResult.error("评价失败",ShowTypeEnum.用户.getValue());
        }finally {
            lock.unlock();
        }
    }

    @ApiOperation("获取骑手位置信息")
    @GetMapping("/locationInfo")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult locationInfo(Long ordersId) {
        return AjaxResult.success(userLocationService.selectUserLocationById(ordersId));
    }

    @ApiOperation("取消/退单理由")
    @PostMapping("/cancelReason")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "configKey", value = "取消订单理由=sys.orders.cancelType;订单退款或退货原因=sys.orders.returnReason", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult cancelReason(String configKey) {
        try {
            String reason = (String) sysConfigService.selectConfigByKey(configKey);
            String[] reasons = reason.split(",");
            return AjaxResult.success(reasons);
        } catch (Exception e) {
            return AjaxResult.success("查询失败" + e.getMessage());
        }
    }


    @ApiOperation("取消订单")
    @PostMapping("/ordersCancel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "cancelRemark", value = "取消订单理由", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult ordersCancel(Long ordersId, String cancelRemark) {
        if (StringUtils.isEmpty(cancelRemark)) {
            return AjaxResult.error("取消理由不能为空", ShowTypeEnum.用户.getValue());
        }
        RLock lock = redissonClient.getLock("ORDERS_UPD:" + ordersId);
        if(lock.isLocked()){
            return AjaxResult.error("服务繁忙",ShowTypeEnum.用户.getValue());
        }
        try {
            lock.lock();
            //订单取消
            if(ordersService.ordersCancel(ordersId, ApiUtils.getUserId(), cancelRemark)){
                return AjaxResult.success("取消成功",ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error("取消失败", ShowTypeEnum.用户.getValue());
        } catch (CustomException e) {
            return AjaxResult.error(e.getMessage(),ShowTypeEnum.用户.getValue());
        }catch (Exception e) {
            return AjaxResult.error("系统异常");
        }finally {
            lock.unlock();
        }

    }

    @ApiOperation("订单退货")
    @PostMapping("/ordersReturn")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(name = "reason", value = "退单理由", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "payment", value = "退款金额", dataType = "BigDecimal", paramType = "query", required = true),
            @ApiImplicitParam(name = "photo", value = "上传图", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "returnType", value = "退单方式 1=退款 2=退货退款", dataType = "BigDecimal", paramType = "query", required = true),
            @ApiImplicitParam(name = "description", value = "申请描述", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(name = "phonenumber", value = "手机号码", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult ordersReturn(OrdersReturn ordersReturn) {
        //redis锁防止表单重复提交
        RedisLock redisLock = new RedisLock(redisTemplate, "ORDERS_UID" + ordersReturn.getOrdersId());
        try {
            if (!redisLock.lockNoRetry()) {
                return AjaxResult.error("服务繁忙", ShowTypeEnum.用户.getValue());
            }
            if (StringUtils.isEmpty(ordersReturn.getDescription())) {
                return AjaxResult.error("退单理由不能为空", ShowTypeEnum.用户.getValue());
            }
            if (!PhoneNumberUtils.isMobile(ordersReturn.getPhonenumber())) {
                return AjaxResult.error("手机号码格式错误", ShowTypeEnum.用户.getValue());
            }
            Orders orders = ordersService.selectOrdersById(ordersReturn.getOrdersId());
            if (orders == null) {
                return AjaxResult.error("订单不存在");
            }
            if (!orders.getPayStatus().equals(CommonEnum.STATUS_20.getValue())) {
                return AjaxResult.error("订单未支付，无法申请", ShowTypeEnum.用户.getValue());
            }
            if (!orders.getStatus().equals(OrdersStatusEnum.已确认收货.getValue())) {
                return AjaxResult.error("未确认收货，无法申请", ShowTypeEnum.用户.getValue());
            }
            List<OrdersGoods> ordersGoods = ordersGoodsService.selectOrderGoodListByOrdersId(ordersReturn.getOrdersId());

            boolean b = ordersGoodsService.updateOrdersGoodsByOrdersId(ordersReturn.getOrdersId());
            if (b == false) {
                throw new CustomException("修改失败");
            }

            //获取商品名称集合，并去掉做后一个+
            String s = "";
            for (OrdersGoods ordersGood : ordersGoods) {
                s = s + ordersGood.getGoodsName() + "+";
            }
            String goodsName = s.substring(0, s.length() - 1);
            if (s.length() > 50) {
                goodsName = goodsName.substring(0, 50) + "***";
            }
            //设置退款状态为进行中
            ordersReturn.setGoodsName(goodsName);
            ordersReturn.setStatus(3);
            if (ordersReturn.getPayment() == null) {
                ordersReturn.setPayment(orders.getPayPrice());
            }
            if ("wxpay".equals(orders.getPayType())) {
                //1 微信支付
                ordersReturn.setPaymentType(1);
            } else {
                //2 支付宝支付
                ordersReturn.setPaymentType(2);
            }
            ordersReturn.setCreateTime(DateUtils.getNowDate());
            ordersReturn.setOrdersNo(orders.getOrdersNo());
            //插入
            int result = ordersReturnService.insertOrdersReturn(ordersReturn, orders.getUserId());
            if (result <= 0) {
                return AjaxResult.error("插入退单信息失败");
            }

            //退单中
            orders.setStatus(CommonEnum.STATUS_50.getValue());
            orders.setUpdateTime(DateUtils.getNowDate());
            orders.setPayment(ordersReturn.getPayment());
            ordersService.updateOrders(orders);
            HashMap<Object, Object> resultMap = Maps.newHashMap();
            resultMap.put("ordersNo", orders.getOrdersNo());
            return AjaxResult.success("退单信息添加成功", resultMap);
        } catch (CustomException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return AjaxResult.error("系统异常");
        } finally {
            redisLock.unlock();
        }
    }

    @ApiOperation("退单信息查询")
    @PostMapping("/queryReturnOrders")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单编号", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult queryReturnOrders(Long orderGoodsId) {
        if (null == orderGoodsId) {
            return AjaxResult.error("orderGoodsId 不能为空");
        }
        ReturnOrdersGoodsVO item=userAccountRecordOrderSingleItemService.getReturnOrdersGoodsVO(orderGoodsId);
        if (item == null) {
            return AjaxResult.error("信息不存在，重新查询");
        }
        return AjaxResult.success("查询成功", item);

    }

    @ApiOperation("取消售后单")
    @GetMapping("/cancelOrdersReturn")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单编号", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult cancelOrdersReturn(Long id) {
        UserAccountRecordOrderSingleItem item=new UserAccountRecordOrderSingleItem();
        item.setId(id);
        userAccountRecordOrderSingleItemService.cancelOrderSingleItem(item);
        return AjaxResult.success();
    }

    @ApiOperation("删除售后单")
    @GetMapping("/delOrdersReturn")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersNo", value = "订单编号", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult delOrdersReturn(Long id) {
        UserAccountRecordOrderSingleItem item=new UserAccountRecordOrderSingleItem();
        item.setId(id);
        userAccountRecordOrderSingleItemService.deleteOrderSingleItem(item);
        return AjaxResult.success();
    }

    @ApiOperation("删除订单")
    @PostMapping("/ordersDel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersId", value = "订单ID", dataType = "Long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult ordersDel(Long ordersId) {
        Orders orders = ordersService.selectOrdersById(ordersId);
        if(null==orders){
            return AjaxResult.error("订单不存在");
        }
        try{
            if(orders.getStatus().equals(OrdersStatusEnum.已确认收货.getValue())){
                orders.setDelFlag("2");
                if(ordersService.updateOrders(orders)<1){
                    return AjaxResult.error("删除订单失败",ShowTypeEnum.用户.getValue());
                }
                //批量评价
                ordersEvaluateService.addEvaluate(orders);
                //订单完结
                mqSendService.sendOrdersEndStatusUpdateAsynMessage(orders.getOrdersNo());
                return AjaxResult.success("删除订单成功",ShowTypeEnum.用户.getValue());

            }
            if(orders.getStatus().equals(OrdersStatusEnum.已关闭.getValue())
                    ||orders.getStatus().equals(OrdersStatusEnum.已取消.getValue())
                    ||orders.getStatus().equals(OrdersStatusEnum.已完结.getValue())){
                orders.setDelFlag("2");
                if(ordersService.updateOrders(orders)<1){
                    return AjaxResult.error("删除订单失败",ShowTypeEnum.用户.getValue());
                }
                return AjaxResult.success("删除订单成功",ShowTypeEnum.用户.getValue());
            }
            return AjaxResult.error("当前状态不能删除订单",ShowTypeEnum.用户.getValue());
        }catch (Exception e){
            log.error(e.getMessage());
            return AjaxResult.error("删除订单失败",ShowTypeEnum.用户.getValue());
        }
    }


    /**
     * 判断是否中奖
     *
     * @param record
     * @param giftId
     * @return
     */
    private boolean getIsWin(AssistRecord record, Long giftId) {
        if (null == record||null==giftId) {
            return false;
        }
        if (null == record.getIsWin() || !record.getIsWin()) {
            return false;
        }
        return record.getGiftId().compareTo(giftId) == 0;
    }
}
